home *** CD-ROM | disk | FTP | other *** search
/ 130 MIDI Tool Box / 130 MIDI Tool Box.iso / midiexsr / midiex1.c next >
Text File  |  1986-11-14  |  12KB  |  478 lines

  1. /****************************************************************************
  2.  *  midiex.c   2/20/86      Copyright (C) 1986 John Bailin, Cantus Corportion
  3.  *
  4.  *  Patch exchange software for the IBM-PC using MPU-401 in dumb mode.
  5.  *
  6.  *  Modified 08/24/86 Jim Bergsten to run under Microsoft "C"
  7.  *  Changes copyright (C) 1986 Jim Bergsten
  8.  *     "creat" call changed to "open" calls.
  9.  *     Symbol "string" defined in routine "edit_space"
  10.  *     Missing open bracket in first "for" stmt. in routine "edit_space"
  11.  *     Some logic changed; some extensions, for example, created files
  12.  *     are now only as long as the system exclusive data received.
  13.  *     Error recovery added so operation can be retried without
  14.  *     restarting the program.
  15.  *     Other minor editorial changes...
  16.  *
  17.  *  Updated by Michael Geary, 11/14/86
  18.  *  These changes are not copyrighted!
  19.  *  (How many silly copyrights do you want to see on this thing?)
  20.  *    Fixed bugs:
  21.  *        Files were not closed on error.
  22.  *        You could ^C out and leave the IRQ2 (INT 0Ah) vector hooked -
  23.  *           now forces BREAK OFF and does all console I/O through BIOS.
  24.  *        Interrupt routine in .ASM file failed to chain to previous
  25.  *        interrupt handler when it wasn't ours.
  26.  *    Function templates and type checking added.
  27.  *    Streamlined the user interface
  28.  *    More and more editorial changes...
  29.  *
  30.  ***************************************************************************/
  31.  
  32. /*
  33.  *  The external data and code declarations are all publics in the 8086
  34.  *  assembler module MIDIINT.ASM.  This program was compiled with the Microsoft
  35.  *  C compiler.
  36.  */
  37.  
  38. /* Force library argument checking */
  39. #define LINT_ARGS
  40.  
  41. #include <ctype.h>
  42. #include <fcntl.h>
  43. #include <sys\types.h>
  44. #include <sys\stat.h>
  45. #include <io.h>
  46. #include <dos.h>
  47. #include <process.h>
  48.  
  49. /* Don't include stdio.h - so inadvertant printf's will be caught */
  50. int cdecl sprintf( char *, char *, ... );
  51.  
  52. typedef unsigned char    BYTE;
  53. typedef unsigned int    WORD;
  54. typedef unsigned long    DWORD;
  55. typedef int        BOOL;
  56.  
  57. #define TRUE        1
  58. #define FALSE        0
  59.  
  60. #define BUFMAX        8192
  61. #define CR        13
  62. #define ESC        27
  63. #define LINE        80
  64.  
  65. /*
  66.  * MIDI equates
  67.  */
  68.  
  69. #define SYSEX        0xF0
  70. #define EOX        0xF7
  71.  
  72.  
  73. /*
  74.  * MPU-401 equates
  75.  */
  76.  
  77. #define UART        0x3F
  78. #define RESET        0xFF
  79.  
  80. /*
  81.  * global declarations
  82.  */
  83.  
  84. extern int recv_data_count;
  85. extern BYTE recv_buf[ ];
  86. extern int  recv_buf_ptr;
  87.  
  88. extern BYTE wait_char;
  89.  
  90. BYTE dump_buf[BUFMAX];
  91. BOOL breakstate;
  92.  
  93. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  94.  
  95. /*
  96.  * Functions in this C file
  97.  */
  98.  
  99. void check_keys( void );
  100. BOOL file_exists( char * );
  101. BOOL get_filename( char *, char * );
  102. char *getstring( char * );
  103. void getword( char * *, char * );
  104. BOOL initialize( void );
  105. void instruct( void );
  106. void main( void );
  107. void menu( void );
  108. void print( char * );
  109. void quit( int );
  110. int  read_dump( char * );
  111. int  receive_dump( void );
  112. BOOL send_dump( int );
  113. BOOL setbreak( BOOL );
  114. BOOL write_dump( char *, int );
  115.  
  116. /*
  117.  * Functions in MIDIINT.ASM
  118.  */
  119.  
  120. WORD fetch_mpu_data( void );
  121. int  get_char( int );
  122. void int10( WORD, WORD, WORD, WORD );
  123. void reset_mpu_vector( void );
  124. BOOL set_mpu_vector( void );
  125. BOOL write_mpu_command( int );
  126. BOOL write_mpu_data( int );
  127.  
  128. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  129.  
  130. void main()
  131. {
  132.     print( "\n\nMIDIEX patch exchange utility.\n" );
  133.     print( "Copyright (C) 1986 by Cantus Corportaion.\n" );
  134.     print( "Modifications (C) 1986 by Jim Bergsten.\n" );
  135.     print( "Version 1.2, updated by Michael Geary.\n" );
  136.     if( ! initialize() ) {
  137.     print( "\nYour MPU isn't responding within MIDIEX's timeout period.\n" );
  138.     print( "Try rebooting your system and starting over.\n" );
  139.     quit( 1 );
  140.     }
  141.     print( "\nThis program allows you to send and receive MIDI System Exclusive\n" );
  142.     print( "data dumps between your PC and a synthesizer or other MIDI device.\n" );
  143.     instruct();
  144.  
  145.     while( TRUE ) menu();
  146.  
  147.     quit( 0 );
  148. }
  149.  
  150. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  151.  
  152. BOOL file_exists( name )
  153.     char *name;
  154. {
  155.     register int f;
  156.  
  157.     if( ( f = open( name, (int)(O_RDONLY|O_BINARY) ) ) < 0 )  return FALSE;
  158.  
  159.     close( f );
  160.     return TRUE;
  161. }
  162.  
  163. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  164.  
  165. BOOL get_filename( prompt, name )
  166.     char *prompt, *name;
  167. {
  168.     char response[LINE];
  169.     char *resp;
  170.  
  171.     if( name[0] )  return TRUE;
  172.  
  173.     print( "\nEnter filename to " );
  174.     print( prompt );
  175.     print( ": " );
  176.     resp = getstring( response );
  177.     getword( &resp, name );
  178.  
  179.     return name[0] != 0;
  180. }
  181.  
  182. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  183.  
  184. BOOL initialize()
  185. {
  186.     breakstate = setbreak( 0 );
  187.     if( ! set_mpu_vector() )  return FALSE;
  188.     write_mpu_command( RESET );
  189.     write_mpu_command( UART );
  190.     return TRUE;
  191. }
  192.  
  193. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  194.  
  195. void instruct()
  196. {
  197.     print( "\nCommands are:\n" );
  198.     print( "  S pathname    to Send a data dump to your synthesizer.\n" );
  199.     print( "  R pathname    to Receive a data dump from your synthesizer.\n\n" );
  200.     print( "Press the Esc key at any time to exit.\n" );
  201. }
  202.  
  203. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  204.  
  205. void menu()
  206. {
  207.     char response[LINE];
  208.     char *resp;
  209.     char name[LINE];
  210.     int  size;
  211.  
  212. prompt:
  213.     print( "\nCommand (S, R, Esc): " );
  214.     resp = getstring( response );
  215.     getword( &resp, name );
  216.  
  217.     switch( name[0] ) {
  218.  
  219.     case 'S':
  220.         getword( &resp, name );
  221.         if( ! get_filename( "send", name ) )  break;
  222.         if( size = read_dump( name ) )  send_dump( size );
  223.         print( "\n" );
  224.         break;
  225.  
  226.     case 'R':
  227.         getword( &resp, name );
  228.         if( ! get_filename( "receive", name ) )  break;
  229.         if( file_exists( name ) ) {
  230.         print( "File already exists, OK to overwrite (Y/N)? " );
  231.         getstring( response );
  232.         if( response[0] != 'Y' )  break;
  233.         }
  234.         if( size = receive_dump() )  write_dump( name, size );
  235.         print( "\n" );
  236.         break;
  237.  
  238.     default:
  239.         instruct();
  240.         goto prompt;
  241.     }
  242. }
  243.  
  244. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  245.  
  246. void quit( exitvalue )
  247.     int exitvalue;
  248. {
  249.     print( "\n\n" );
  250.     write_mpu_command( RESET );
  251.     reset_mpu_vector();
  252.     setbreak( breakstate );
  253.     _exit( exitvalue );
  254. }
  255.  
  256. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  257.  
  258. int read_dump( name )
  259.     char *name;
  260. {
  261.     register int f, size;
  262.  
  263.     if( ( f = open( name, (int)(O_RDONLY|O_BINARY) ) ) < 0 ) {
  264.     print( "\nUnable to open input file " );
  265.     print( name );
  266.     return FALSE;
  267.     }
  268.  
  269.     if( ( size = read( f, dump_buf, BUFMAX ) ) <= 0 ) {
  270.     close( f );
  271.     print( "\nTrouble reading input file " );
  272.     print( name );
  273.     return FALSE;
  274.     }
  275.  
  276.     close( f );
  277.     return size;
  278. }
  279.  
  280. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  281.  
  282. int receive_dump()
  283. {
  284.     register int i, j, k;
  285.     char printbuf[40];
  286.  
  287.     /* Set character to wait for */
  288.     wait_char = EOX;
  289.  
  290.     print( "\nSend the MIDI data now...\n" );
  291.     while( wait_char )    check_keys();
  292.  
  293. /*  The following dumps the received data in hexadecimal.
  294.     remove the comments around it if you want this display. */
  295.  
  296. /*  print( "MIDI data received...\n" );
  297.     j = 0;
  298.     for( i = 0;  i < recv_buf_ptr;  ++i ) {
  299.     sprintf( printbuf, " %2.2X", recv_buf[i] );
  300.     print( printbuf );
  301.     if( j++ == 15 ) {
  302.         print( "\n" );
  303.         j = 0;
  304.      }
  305.     }
  306.     if( j )  print( "\n" );
  307. */
  308.  
  309.     /* search backwards for start of dump */
  310.     i = recv_buf_ptr;
  311.  
  312.     for( k = 1;  k <= BUFMAX;  k++ ) {
  313.     if( --i < 0 )  i = BUFMAX;
  314.     if ( recv_buf[i] == SYSEX )  break ;
  315.     }
  316.  
  317.     if( k >= BUFMAX ) {
  318.     print( "Start of MIDI dump not found\n" );
  319.     return 0;
  320.     }
  321.  
  322.     sprintf( printbuf, "Size of dump is %d\n", k );
  323.     print( printbuf );
  324.  
  325.     for ( j = 0;  j < k;  j++ ) {
  326.     if( i == BUFMAX )  i = 0;
  327.     dump_buf[ j ] = recv_buf[ i++ ];
  328.     }
  329.  
  330.     return k;
  331. }
  332.  
  333. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  334.  
  335. BOOL send_dump( size )
  336.     int size;
  337. {
  338.     register int i;
  339.  
  340.     print( "\nStrike any key when ready to send MIDI data...\n" );
  341.     get_char( 0 );
  342.     print( "\nSending MIDI data...\n" );
  343.     for (i =  0; i <= size; i++) {
  344.     if( ! write_mpu_data( dump_buf[i] ) ) {
  345.         print( "MIDI interface timed out\n" );
  346.         return FALSE;
  347.     }
  348.     check_keys();
  349.     if( dump_buf[i] == EOX )  break;
  350.     }
  351.     print( "\nDone!" );
  352.     return TRUE;
  353. }
  354.  
  355. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  356.  
  357. BOOL setbreak( newstate )
  358.     BOOL newstate;
  359. /*
  360.  *  Sets DOS Ctrl-Break checking to newstate and returns previous state.
  361.  */
  362. {
  363.     BOOL oldstate;
  364.     union REGS regs;
  365.  
  366.     regs.x.ax = 0x3300;
  367.     intdos( ®s, ®s );
  368.     oldstate = (BOOL)regs.h.dl;
  369.  
  370.     regs.x.ax = 0x3301;
  371.     regs.h.dl = (unsigned char)newstate;
  372.     intdos( ®s, ®s );
  373.  
  374.     return oldstate;
  375. }
  376.  
  377. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  378.  
  379. BOOL write_dump( name, size )
  380.     register char *name;
  381.     int size;
  382. {
  383.     register int f;
  384.  
  385.     if( ( f = open( name, (int)(O_CREAT|O_TRUNC|O_WRONLY|O_BINARY), S_IWRITE ) ) < 0 ) {
  386.     print( "\nUnable to open output file " );
  387.     print( name );
  388.     return FALSE;
  389.     }
  390.  
  391.     if( write( f, dump_buf, size ) != size ) {
  392.     close( f );
  393.     print( "\nTrouble writing to output file " );
  394.     print( name );
  395.     return FALSE;
  396.     }
  397.  
  398.     close( f );
  399.     print( "\nDone!" );
  400.     return TRUE;
  401. }
  402.  
  403. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  404.  
  405. /*
  406.  *
  407.  * lower level editing routines
  408.  *
  409.  */
  410.  
  411. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  412.  
  413. void check_keys()
  414. {
  415.     register char c;
  416.  
  417.     if( get_char( 1 ) == 1 ) {
  418.     c = (char)( get_char( 0 ) & 0xFF );
  419.     if( c == ESC )    quit( 0 );
  420.     }
  421. }
  422.  
  423. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  424.  
  425. char *getstring( string )
  426.     char *string;
  427. {
  428.     register int x = 0;
  429.     register char c;
  430.  
  431.     while( TRUE ) {
  432.     c = (char)( get_char( 0 ) & 0xFF );
  433.     if( c == ESC )    quit( 0 );
  434.     if( c == CR ) {
  435.         print( "\n" );
  436.         string[x] = '\0';
  437.         return string;
  438.     }
  439.     if( ( c >= 32 && c < 127 ) || c == CR ) {
  440.         string[ x++ ] = toupper( c );
  441.         int10( 0x0E00 | c, 0, 0, 0 );
  442.     } else if( c == 8  &&  x > 0 ) {
  443.         int10( 0x0E00 | c, 0, 0, 0 );
  444.         int10( 0x0A00 | ' ', 7, 1, 0 );
  445.         --x;
  446.     }
  447.     }
  448. }
  449.  
  450. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  451.  
  452. void getword( strpp, word )
  453.     char **strpp;
  454.     char *word;
  455. {
  456.     char *wordp;
  457.  
  458.     wordp = word;
  459.     while( isspace( **strpp ) ) (*strpp)++;
  460.     while( **strpp && ! isspace( **strpp ) )  *wordp++ = *(*strpp)++;
  461.     *wordp = 0;
  462. }
  463.  
  464. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  465.  
  466. void print( string )
  467.     register char *string;
  468. {
  469.     register char c;
  470.  
  471.     while( c = *string++ ) {
  472.     if( c == '\n' )  int10( 0x0E00 | '\r', 0, 0, 0 );
  473.     int10( 0x0E00 | c, 0, 0, 0 );
  474.     }
  475. }
  476.  
  477. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  478.